// 版权归 瞄你个汪 所有。使用本代码应遵守相关法律法规和Apache 2.0开源许可要求。
package top.geeke.config.swagger;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import top.geeke.Application;
import top.geeke.config.AppConfiguration;
import top.geeke.constants.AppConstPool;
import top.geeke.toolkit.SpringBeanManager;

import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * <p>
 * Swagger配置类
 * </p>
 * @author 瞄你个汪
 * @since 2024-05-01 12:00:00
 */
@EnableOpenApi
@Configuration
public class Swagger3Config {
    @Bean
    public Docket createSwaggerApi() {
        SwaggerOption config = SpringBeanManager.getBean(SwaggerOption.class);
        return new Docket(DocumentationType.OAS_30)
                .pathMapping("/")

                // 定义是否开启swagger，false为关闭，可以通过变量控制
                .enable(config.getEnabled())

                // 将api的元信息设置为包含在json ResourceListing响应中。
                .apiInfo(apiInfo())

                // 接口调试地址
                //.host(config.getHost())

                // 选择哪些接口作为swagger的doc发布
                .select()
                .apis(RequestHandlerSelectors.basePackage(Application.class.getPackage().getName()))
                .paths(PathSelectors.any())
                .build()

                //.groupName("系统默认")

                // 支持的通讯协议集合
                .protocols(newHashSet("https","http"))

                // 授权信息设置，必要的header token等认证信息
                .securitySchemes(Collections.singletonList(tokenScheme()))

                // 授权信息全局应用
                .securityContexts(Collections.singletonList(tokenContext()));
    }

    /**
     * api描述信息
     */
    private ApiInfo apiInfo() {
        SwaggerOption config = SpringBeanManager.getBean(SwaggerOption.class);
        AppConfiguration appConfig = SpringBeanManager.getBean(AppConfiguration.class);
        return new ApiInfoBuilder()
                .title(appConfig.getName() + " API 文档")
                .description(config.getDescription())
                .version(appConfig.getVersion())
                .contact(new Contact(
                        config.getAuthor(),
                        config.getGitAddress(),
                        config.getEmail())
                )
                .build();
    }

    private HttpAuthenticationScheme tokenScheme() {
        return HttpAuthenticationScheme.JWT_BEARER_BUILDER.name(AppConstPool.AUTHORIZATION_KEY).build();
    }

    /**
     * 配置安全上下文
     */
    private SecurityContext tokenContext() {
        return SecurityContext.builder()
                .securityReferences(Collections.singletonList(SecurityReference.builder()
                        .scopes(new AuthorizationScope[0])
                        .reference(AppConstPool.AUTHORIZATION_KEY)
                        .build()))
                .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
                .build();
    }

    @SafeVarargs
    private final <T> Set<T> newHashSet(T... ts) {
        if (ts.length > 0) {
            return new LinkedHashSet<>(Arrays.asList(ts));
        }
        return null;
    }
}